import dayjs from "dayjs"
import { useCallback, useEffect, useRef, useState } from "react"

/**
 * 高精度倒計時 Hook
 *
 * @param initialSeconds 初始倒計時秒數
 * @param onEnd 倒計時結束時的回調
 * @returns 包含當前倒計時狀態和控制方法的對象
 */
export function useCountDown(
    initialSeconds: number,
    onEnd?: () => void,
): {
    count: number
    isEnd: boolean
    reset: () => void
} {
    // 驗證輸入參數
    if (initialSeconds < 0) {
        console.warn("useCountDown: initialSeconds 不能為負數，已重置為 0")
        initialSeconds = 0
    }

    // 使用 refs 存儲不觸發渲染的值
    const initialSecondsRef = useRef<number>(initialSeconds)
    const endTimeRef = useRef<dayjs.Dayjs | null>(null)
    const timerRef = useRef<number | null>(null)
    const onEndRef = useRef(onEnd)
    const hasCalledEndRef = useRef(false)

    // 倒計時狀態
    const [remainingSeconds, setRemainingSeconds] = useState<number>(initialSeconds)

    // 更新回調引用，避免閉包問題
    useEffect(() => {
        onEndRef.current = onEnd
    }, [onEnd])

    // 清除計時器
    const clearTimer = useCallback(() => {
        if (timerRef.current !== null) {
            window.clearInterval(timerRef.current)
            timerRef.current = null
        }
    }, [])

    // 開始計時器
    const startTimer = useCallback(() => {
        // 先清除現有計時器
        clearTimer()

        // 重置結束回調標記
        hasCalledEndRef.current = false

        // 設定結束時間點
        const seconds = initialSecondsRef.current
        if (seconds <= 0) {
            setRemainingSeconds(0)
            hasCalledEndRef.current = true
            onEndRef.current?.()
            return
        }

        // 計算目標時間
        endTimeRef.current = dayjs().add(seconds, "second")
        setRemainingSeconds(seconds)

        // 啟動精確計時器
        timerRef.current = window.setInterval(() => {
            const now = dayjs()
            const endTime = endTimeRef.current

            if (!endTime) return

            // 計算剩餘時間（使用 true 參數獲取精確小數）
            const diff = endTime.diff(now, "second", true)
            // 取整並確保不為負數
            const remaining = Math.max(0, Math.floor(diff))

            setRemainingSeconds(remaining)

            // 處理倒計時結束
            if (remaining <= 0 && !hasCalledEndRef.current) {
                hasCalledEndRef.current = true
                clearTimer()
                onEndRef.current?.()
            }
        }, 200) // 使用較小間隔提高精度，但避免過高頻率導致性能問題
    }, [clearTimer])

    // 重置計時器
    const reset = useCallback(() => {
        startTimer()
    }, [startTimer])

    // 處理初始秒數變化
    useEffect(() => {
        initialSecondsRef.current = initialSeconds
        // 如果計時器已啟動，則重新開始
        if (timerRef.current !== null) {
            startTimer()
        }
    }, [initialSeconds, startTimer])

    // 組件掛載時啟動計時器
    useEffect(() => {
        startTimer()

        // 組件卸載時清理資源
        return () => {
            clearTimer()
        }
    }, [startTimer, clearTimer])

    // 返回公開的 API
    return {
        count: remainingSeconds,
        isEnd: remainingSeconds <= 0,
        reset,
    }
}
